// Copyright 2022 Huawei Cloud Computing Technology Co., Ltd.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef CLOUDAPPENGINE_CAELOGCONGFIG_H
#define CLOUDAPPENGINE_CAELOGCONGFIG_H

#include <cstring>
#include <unistd.h>
#include <thread>
#include <sstream>
#include <android/log.h>
#include "CaeConfigManage.h"
#include "CaeThread.h"
#include "../hwsecure/securec.h"
#define TAG "CAE"
const int CHAR_SIZE = 1000;
const int LOG_DEBUG_BUF_SIZE = 2000;
const int LOG_INFO_BUF_SIZE = 1000;
const int LOG_WARN_BUF_SIZE = 1000;
const int LOG_ERROR_BUF_SIZE = 1000;

inline char *CaeStrrchr(const char *str, int c);

#define FILENAME1 \
    (strcmp(CaeStrrchr(__FILE__, '\\'), (char *)"") != 0 ? (CaeStrrchr(__FILE__, '\\') + 1) : __FILE__)
#define FILENAME \
    (strcmp(CaeStrrchr(FILENAME1, '/'), (char *)"") != 0 ? (CaeStrrchr(FILENAME1, '/') + 1) : FILENAME1)

#define LOGD(fmt, ...) LogDebug(FILENAME, __LINE__, __FUNCTION__, fmt, ##__VA_ARGS__)
#define LOGI(fmt, ...) LogInfo(FILENAME, __LINE__, __FUNCTION__, fmt, ##__VA_ARGS__)
#define LOGW(fmt, ...) LogWarn(FILENAME, __LINE__, __FUNCTION__, fmt, ##__VA_ARGS__)
#define LOGE(fmt, ...) LogError(FILENAME, __LINE__, __FUNCTION__, fmt, ##__VA_ARGS__)


inline void Log(int level, const char *filename, int line, const char *function, const char *msg) noexcept
{
#if PRINT_THREAD_ID
    std::__thread_id threadId = std::this_thread::get_id();
    std::stringstream ss_ID;
    ss_ID << threadId;
    std::string msgInfo = "[threadId:" + ss_ID.str() + "]" + std::string(msg);
#else
    std::string msgInfo = std::string(msg);
#endif
    __android_log_print(level, TAG, "[%s:%d]%s():%s", filename, line, function, msgInfo.c_str());
}

inline void LogDebug(const char *filename, int line, const char *function, const char *fmt, ...) noexcept
{
    if (CaeConfigManage::GetLogLevel() != ANDROID_LOG_DEBUG) {
        return;
    }
    char msg[LOG_DEBUG_BUF_SIZE] = {0};
    va_list args;
    va_start(args, fmt);
    int ret = vsnprintf_s(msg, LOG_DEBUG_BUF_SIZE, LOG_DEBUG_BUF_SIZE - 1, fmt, args);
    if (ret != -1) {
        Log(ANDROID_LOG_DEBUG, filename, line, function, msg);
    }
    va_end(args);
}

inline void LogInfo(const char *filename, int line, const char *function, const char *fmt, ...) noexcept
{
    if (CaeConfigManage::GetLogLevel() != ANDROID_LOG_DEBUG && CaeConfigManage::GetLogLevel() != ANDROID_LOG_INFO) {
        return;
    }
    char msg[LOG_INFO_BUF_SIZE] = {0};
    va_list args;
    va_start(args, fmt);
    int ret = vsnprintf_s(msg, LOG_INFO_BUF_SIZE, LOG_INFO_BUF_SIZE - 1, fmt, args);
    if (ret != -1) {
        Log(ANDROID_LOG_INFO, filename, line, function, msg);
    }
    va_end(args);
}

inline void LogWarn(const char *filename, int line, const char *function, const char *fmt, ...) noexcept
{
    char msg[LOG_WARN_BUF_SIZE] = {0};
    va_list args;
    va_start(args, fmt);
    int ret = vsnprintf_s(msg, LOG_WARN_BUF_SIZE, LOG_WARN_BUF_SIZE - 1, fmt, args);
    if (ret != -1) {
        Log(ANDROID_LOG_WARN, filename, line, function, msg);
    }
    va_end(args);
}

inline void LogError(const char *filename, int line, const char *function, const char *fmt, ...) noexcept
{
    char msg[LOG_ERROR_BUF_SIZE] = {0};
    va_list args;
    va_start(args, fmt);
    int ret = vsnprintf_s(msg, LOG_ERROR_BUF_SIZE, LOG_ERROR_BUF_SIZE - 1, fmt, args);
    if (ret != -1) {
        Log(ANDROID_LOG_ERROR, filename, line, function, msg);
    }
    va_end(args);
}

inline char *CaeStrrchr(const char *str, char c) noexcept
{
    const char *ret = str;
    while (*str) {
        ++str;
    }
    while ((*str != c) && (str >= ret)) {
        --str;
    }
    if (str >= ret) {
        return (char *)str;
    }
    return (char *)"";
}

#endif // CLOUDAPPENGINE_CAELOGCONGFIG_H
